#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h> 
#include <stdlib.h>       
#include <string.h>
#include <pthread.h>
//#include <sys/sem.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <sys/poll.h>
#include <sys/epoll.h>

#include "common.h"

extern SystemParam* pgSystemParam;

void Mp4FileOpen(SaveInfo *pSaveInfo,PictureInfo *pPictureInfo,time_t t)
{
		struct tm tim = *localtime(&t);	
		
		sprintf(pSaveInfo->sMp4PathTemp,"mkdir -p %s/%04d%02d%02d",pgSystemParam->cSaveDir,1900+tim.tm_year,tim.tm_mon+1,tim.tm_mday);
		system(pSaveInfo->sMp4PathTemp);
		
		printf("pSaveInfo->sType,pPictureInfo->s = %s,%s\n", pSaveInfo->sType,pPictureInfo->s);
		
		sprintf(pSaveInfo->sMp4Path,"%s/%04d%02d%02d/tmp_%s_%c_%04d%02d%02d%02d%02d%02d.mp4",
						pgSystemParam->cSaveDir,1900+tim.tm_year,tim.tm_mon+1,tim.tm_mday,pSaveInfo->sType,pPictureInfo->s,
						1900+tim.tm_year,tim.tm_mon+1,tim.tm_mday,tim.tm_hour,tim.tm_min,tim.tm_sec);		
		
		//sprintf(pSaveInfo->sMp4Path, "/sdcard/opentest.mp4");
		
		if( ( pSaveInfo->m_hMp4 = MP4Create(pSaveInfo->sMp4Path,MP4_CREATE_64BIT_DATA) ) == MP4_INVALID_FILE_HANDLE )
		{
				writeLog("MP4Create failed",__FILE__,__LINE__);
				writeLog(pSaveInfo->sMp4Path,__FILE__,__LINE__); 	
				return;			
 		}		
 		
 		printf("@@@@@@@@@@@@@@@@@@open mp4 file ok !\n");
 		
		if(	( pSaveInfo->videoMp4Track = MP4AddH264VideoTrack(pSaveInfo->m_hMp4, 
											90000, 90000 / pSaveInfo->frameRate, pPictureInfo->w, pPictureInfo->h, 
											pSaveInfo->pSps[1], pSaveInfo->pSps[2], pSaveInfo->pSps[3], 3) ) 
				 						== MP4_INVALID_TRACK_ID ) 
		{
				writeLog("MP4AddH264VideoTrack failed",__FILE__,__LINE__);
				writeLog(pSaveInfo->sMp4Path,__FILE__,__LINE__); 	
				MP4Close(pSaveInfo->m_hMp4);
				pSaveInfo->m_hMp4 = MP4_INVALID_FILE_HANDLE;
				return;						
		}		
		
		MP4AddH264SequenceParameterSet(pSaveInfo->m_hMp4,pSaveInfo->videoMp4Track,
																	(const uint8_t*)pSaveInfo->pSps,pSaveInfo->numSPS);
		MP4AddH264PictureParameterSet(pSaveInfo->m_hMp4,pSaveInfo->videoMp4Track,
																	(const uint8_t*)pSaveInfo->pPps,pSaveInfo->numPPS);	

		static int  iAudioObjectType;
		static int  iAudioSamplingFrequencyIndex;
		static int  iAudioChannelConfiguration;
		struct audioSource *pAudioSource = GetComposedAudioSource();
		
		pthread_mutex_lock (&(pAudioSource->Lock));
		iAudioObjectType = pAudioSource->iAudioObjectType;
		iAudioSamplingFrequencyIndex = pAudioSource->iAudioSamplingFrequencyIndex;
		iAudioChannelConfiguration = pAudioSource->iAudioChannelConfiguration;
		pthread_mutex_unlock (&(pAudioSource->Lock));						
							
		if( ( pSaveInfo->audioMp4Track = MP4AddAudioTrack(pSaveInfo->m_hMp4, 
							GetSamplingRate(iAudioSamplingFrequencyIndex), 1024, MP4_MPEG4_AUDIO_TYPE) )
							== MP4_INVALID_TRACK_ID )
		{
				writeLog("MP4AddH264VideoTrack failed",__FILE__,__LINE__);
				writeLog(pSaveInfo->sMp4Path,__FILE__,__LINE__); 	
				MP4Close(pSaveInfo->m_hMp4);
				pSaveInfo->m_hMp4 = MP4_INVALID_FILE_HANDLE;
				pSaveInfo->videoMp4Track = MP4_INVALID_TRACK_ID;
				return;	
		}	
		
		unsigned char buf[2];
		buf[0]  = ( iAudioObjectType << 3 ) | 
							( iAudioSamplingFrequencyIndex >> 1 );
		buf[1]  = ( iAudioSamplingFrequencyIndex << 7 ) | 
							( iAudioChannelConfiguration << 3 );	
		MP4SetTrackESConfiguration(pSaveInfo->m_hMp4,pSaveInfo->audioMp4Track,(const uint8_t*)buf,2);		
		printf("%d,%d======================\n",pPictureInfo->w,pPictureInfo->h);						
}

void Mp4VideoData(SaveInfo *pSaveInfo,PictureInfo *pPictureInfo,unsigned char *pData,int iSize)
{
		//sprintf("%d,%d-----------------\n",pPictureInfo->w,pPictureInfo->h);
		unsigned char *pTmp = pData;		
		unsigned char *pBuf;	
		int   ret,size;		
				
		while( 1 )
		{
				ret = GetCode(pTmp,pData+iSize-pTmp,&pBuf,&size);
			
				if( ( ret == 0 ) || ( ret == 1 ) )	
				{																	
						if( ( *pBuf == 0x67 ) || ( *pBuf == 0x68 ) || ( *pBuf == 0x06 ) )	
						{	
																 	
						}				
						else
						{
								if( size < ( AUDIO_DELAY_SIZE - 4 ) )
								{
										pSaveInfo->pBuffer[0] = 0xFF & ( size >> 24 );		
										pSaveInfo->pBuffer[1] = 0xFF & ( size >> 16 );	
										pSaveInfo->pBuffer[2] = 0xFF & ( size >> 8 );		
										pSaveInfo->pBuffer[3] = 0xFF & ( size );
										memcpy(pSaveInfo->pBuffer+4,pBuf,size);
										MP4WriteSample(pSaveInfo->m_hMp4, pSaveInfo->videoMp4Track,(const uint8_t*)pSaveInfo->pBuffer,4+size, 
																	 MP4_INVALID_DURATION, 0, *pBuf == 0x65);
								}									
						}					
				}
				
				pTmp = pBuf + size;
								
				if( ( ret == 0 ) || ( ret == -1 ) )	break;
		}	
}

void Mp4AudioData(SaveInfo *pSaveInfo,unsigned char *pData,int iSize)
{
		MP4WriteSample(pSaveInfo->m_hMp4, pSaveInfo->audioMp4Track, (const uint8_t*)pData+7,iSize-7, MP4_INVALID_DURATION, 0,1);
}

void Mp4Close(SaveInfo *pSaveInfo,time_t t)
{		
		printf("into Mp4Close\n");
		int ret;
		char pBuf[90];	
	
		struct tm tim = *localtime(&t);		
	
		char *pTmp;
		
		if( ( pTmp = strstr(pSaveInfo->sMp4Path,"tmp_") ) == NULL ) return;

		*pTmp = '\0';	
		sprintf(pSaveInfo->sMp4PathTemp,"%s%s",pSaveInfo->sMp4Path,pTmp+4);
		*pTmp = 't';		
		
		printf("1 %s,%s\n", pSaveInfo->sMp4Path, pSaveInfo->sMp4PathTemp);
		
		rename(pSaveInfo->sMp4Path,pSaveInfo->sMp4PathTemp);
		strcpy(pSaveInfo->sMp4Path,pSaveInfo->sMp4PathTemp);		
		
		printf("2 %s,%s\n", pSaveInfo->sMp4Path, pSaveInfo->sMp4PathTemp);
		
		if( ( pTmp = strstr(pSaveInfo->sMp4Path,".mp4") ) == NULL ) return;
		
		*pTmp = '\0';		
		sprintf(pSaveInfo->sMp4PathTemp,"%s_%04d%02d%02d%02d%02d%02d.mp4",pSaveInfo->sMp4Path,1900+tim.tm_year,tim.tm_mon+1,tim.tm_mday,tim.tm_hour,tim.tm_min,tim.tm_sec);	
		*pTmp = '.';
		
		printf("3 %s,%s\n", pSaveInfo->sMp4Path, pSaveInfo->sMp4PathTemp);
		
		rename(pSaveInfo->sMp4Path,pSaveInfo->sMp4PathTemp);		
		
		printf("4 %s,%s\n", pSaveInfo->sMp4Path, pSaveInfo->sMp4PathTemp);																				
}
